using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using CellarDoor.Gui;

namespace CellarDoor.Gui.Theming
{
    public class UiTheme
    {
        /// <summary>
        /// Fonts in this theme
        /// </summary>
        private List<UiThemeFont> fonts = new List<UiThemeFont>();

        /// <summary>
        /// Element sprite definitions
        /// </summary>
        private List<UiThemeElement> elements = new List<UiThemeElement>();

        /// <summary>
        /// Icons and other sprites
        /// </summary>
        private List<UiThemeSprite> sprites = new List<UiThemeSprite>();

        public UiTheme(IEnumerable<UiThemeElement> elements, IEnumerable<UiThemeFont> fonts)
            : this (elements, fonts, null)
        {
        }

        public UiTheme(IEnumerable<UiThemeElement> elements, IEnumerable<UiThemeFont> fonts, List<UiThemeSprite> sprites)
        {
            if (elements == null)
            {
                throw new ArgumentNullException("elements");
            }
            if (fonts == null)
            {
                throw new ArgumentNullException("fonts");
            }
            if (sprites == null)
            {
                sprites = new List<UiThemeSprite>();
            }

            this.elements.AddRange(elements);
            this.fonts.AddRange(fonts);
            this.sprites.AddRange(sprites);

            if (this.elements.Count == 0)
            {
                throw new ArgumentException("elements was empty");
            }
            if (this.fonts.Count == 0)
            {
                throw new ArgumentException("fonts was empty");
            }
        }
        
        public SpriteFont GetFont(string fontName, int resX, int resY)
        {
            return (GetItem(fontName, resY, resY, fonts, true) as UiThemeFont).Font;
        }

        public UiThemeElement GetElement(string elementName, int resX, int resY)
        {
            return (GetItem(elementName, resY, resY, elements, true) as UiThemeElement);
        }

        public UiThemeSprite GetState(string elementName, string stateName, int resX, int resY)
        {
            return GetElement(elementName, resX, resY).GetState(stateName);
        }

        public UiThemeSprite GetSprite(string name, int resX, int resY)
        {
            return (GetItem(name, resY, resY, sprites, false) as UiThemeSprite);
        }

        private INamedWithResolution GetItem(string name, int resX, int resY, IEnumerable<INamedWithResolution> items, bool withDefault)
        {
            int resolution = resX * resY;

            INamedWithResolution result = null;

            foreach (INamedWithResolution item in items)
            {
                if (result == null && withDefault)
                {
                    result = item;
                }

                if (String.Compare(name, item.Name, StringComparison.InvariantCultureIgnoreCase) != 0)
                {
                    continue;
                }

                if (Math.Abs(resolution - item.Resolution) <= Math.Abs(resolution - item.Resolution))
                {
                    result = item;
                }
            }

            return result;
        }
    }
}
